import 'dart:async';

import 'package:date_format/date_format.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_picker/picker.dart';

import '../../config/public_color.dart';
import '../../config/public_language.dart';
import '../../config/public_text.dart';
import '../../extension/date_time_extension.dart';
import '../../foundation/localizations/public_cupertino_localizations.dart';
import '../../foundation/style/bold_text_style.dart';
import '../../foundation/style/normal_text_style.dart';
import '../../model/language.dart';
import '../sheet/modal_bottom_sheet.dart';

/// FileName date_picker
///
/// @Author lax
/// @Date 2024/6/12
///
/// @Description

enum DateShowType {
  bottomSheet,
  dialog,
}

extension DateTimeType on DateType {
  int? pickerDateTimeType() {
    return {
      DateType.kYMDHMS: PickerDateTimeType.kYMDHMS,
      DateType.kYMDHM: PickerDateTimeType.kYMDHM,
      DateType.kYMD: PickerDateTimeType.kYMD,
      DateType.kyMD: PickerDateTimeType.kYMD,
      DateType.kYM: PickerDateTimeType.kYM,
      DateType.kMDHM: PickerDateTimeType.kYMDHM,
      DateType.kMDHMS: PickerDateTimeType.kYMDHMS,
      DateType.kMD: PickerDateTimeType.kYMD,
      DateType.kHMS: PickerDateTimeType.kHMS,
      DateType.kHM: PickerDateTimeType.kHM,
    }[this];
  }
}

class DatePicker {
  static Future<String> showBottomSheet({
    required BuildContext context,
    DateType? dateType,
    String? title,
    String? value,
    Function(String dateStr)? onConfirm,
    Function? assemblySelect,
    DateTime? minDate,
    DateTime? maxDate,
  }) {
    return DatePicker.show(
      context: context,
      showType: DateShowType.bottomSheet,
      dateType: dateType,
      title: title,
      value: value,
      onConfirm: onConfirm,
      assemblySelect: assemblySelect,
      minDate: minDate,
      maxDate: maxDate,
    );
  }

  static Future<String> showDialog({
    required BuildContext context,
    DateType? dateType,
    String? title,
    String? value,
    Function(String dateStr)? onConfirm,
    Function? assemblySelect,
    DateTime? minDate,
    DateTime? maxDate,
  }) {
    return DatePicker.show(
      context: context,
      showType: DateShowType.dialog,
      dateType: dateType,
      title: title,
      value: value,
      onConfirm: onConfirm,
      assemblySelect: assemblySelect,
      minDate: minDate,
      maxDate: maxDate,
    );
  }

  static Future<String> show({
    required BuildContext context,
    DateShowType? showType = DateShowType.bottomSheet,
    DateType? dateType = DateType.kYMD,
    String? title,
    String? value,
    Function(String dateStr)? onConfirm,
    Function? assemblySelect,
    DateTime? minDate,
    DateTime? maxDate,
  }) {
    FocusScope.of(context).requestFocus(FocusNode());
    Completer<String> completer = Completer();
    final picker = Picker(
      height: 260,
      itemExtent: 40,
      adapter: DateTimePickerAdapter(
        type: dateType?.pickerDateTimeType() ?? PickerDateTimeType.kYMD,
        value: DateTime.tryParse(value ?? ''),
        minValue: minDate,
        maxValue: maxDate,
        months: getMonthDataSource(),
        yearSuffix: PublicLanguage.language == Language.english ? null : PublicText.year,
        daySuffix: PublicLanguage.language == Language.english ? null :PublicText.day,
      ),
      title: Text(
        title ?? PublicText.pleaseSelect,
        style: BoldTextStyle(),
      ),
      headerDecoration: const BoxDecoration(),
      hideHeader: showType == DateShowType.dialog,
      headerColor: Colors.transparent,
      confirmText: PublicText.confirm,
      cancelText: PublicText.cancel,
      backgroundColor: Colors.transparent,
      textStyle: NormalTextStyle(fontSize: 16, color: PublicColor.darkText),
      selectedTextStyle:
          BoldTextStyle(fontSize: 18, color: PublicColor.primary),
      cancelTextStyle: BoldTextStyle(color: PublicColor.grayText),
      confirmTextStyle: BoldTextStyle(color: PublicColor.primary),
      onConfirm: (Picker picker, List value) {
        final date = (picker.adapter as DateTimePickerAdapter).value;
        if (date != null) {
          String dateResult = formatDate(date, dateType?.dateFormats() ?? []);
          if (onConfirm != null) {
            onConfirm(dateResult);
          }
          if (assemblySelect != null) {
            assemblySelect(dateResult);
          }
          completer.complete(dateResult);
        }
      },
    );

    if (showType == DateShowType.dialog) {
      picker.showDialog(
        context,
        backgroundColor: Colors.white,
      );
    } else {
      ModalBottomSheet.show(
        context: context,
        child: picker.makePicker(
          ThemeData(
            dialogBackgroundColor: Colors.transparent,
            dividerColor: PublicColor.divider,
          ),
        ),
      );
    }

    return completer.future;
  }

  static List<String> getMonthDataSource() {
    return [
      PublicText.month1,
      PublicText.month2,
      PublicText.month3,
      PublicText.month4,
      PublicText.month5,
      PublicText.month6,
      PublicText.month7,
      PublicText.month8,
      PublicText.month9,
      PublicText.month10,
      PublicText.month11,
      PublicText.month12,
    ];
  }

  static Future<String> systemDatePicker({
    required BuildContext context,
    CupertinoDatePickerMode mode = CupertinoDatePickerMode.date,
    DateTime? minimumDate,
    DateTime? maximumDate,
    String? value,
    ValueChanged<String>? onConfirm,
  }) async {
    String result = value ?? DateTime.now().dateString();
    final dateType = {
      CupertinoDatePickerMode.date: DateType.kYMD,
      CupertinoDatePickerMode.time: DateType.kHM,
      CupertinoDatePickerMode.dateAndTime: DateType.kMDHM,
    }[mode];
    final local = Localizations.localeOf(context).toString() != 'en_US';
    final picker = CupertinoDatePicker(
      mode: mode,
      minimumDate: minimumDate,
      maximumDate: maximumDate,
      initialDateTime: DateTime.tryParse(value ?? ''),
      use24hFormat: true,
      onDateTimeChanged: (dayTime) {
        result = dayTime.dateTimeString(dateType: dateType);
      },
    );
    final date = await ModalBottomSheet.showConfirmSheet(
      context: context,
      height: MediaQuery.of(context).size.height / 5 * 2,
      onConfirm: () {
        onConfirm?.call(result);
        return result;
      },
      child: local
          ? Localizations.override(
              context: context,
              locale: Locale(PublicLanguage.languageLocalCode),
              delegates: const [PublicCupertinoLocalizations.delegate],
              child: picker,
            )
          : picker,
    );
    return date is String ? date : '';
  }
}
